/**
 * 
 */
package org.xelnaga.defiler.web.interceptor;

import java.util.Date;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.jboss.seam.wiki.core.action.prefs.WikiPreferences;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.util.WebUtils;
import org.xelnaga.defiler.context.UserContext;
import org.xelnaga.defiler.domain.ClickstreamModel;
import org.xelnaga.defiler.domain.ClickstreamRequestModel;
import org.xelnaga.defiler.domain.HtmlPageModel;
import org.xelnaga.defiler.domain.SiteModel;
import org.xelnaga.defiler.service.ClickstreamService;
import org.xelnaga.defiler.web.page.mapping.PageResolver;
import org.xelnaga.defiler.web.util.BotChecker;
import org.xelnaga.defiler.web.util.BrowserSniffer;
import org.xelnaga.defiler.web.util.WebKeys;

/**
 * @author qijb
 *
 */
@Component
public class ClickstreamFactory {
    @Autowired
    private PageResolver pageResolver;
    @Autowired
    private WikiPreferences wikiPreferences;
    @Autowired
    private ClickstreamService clickStreamService;
	/**
	 * 
	 */
	public ClickstreamFactory() {
		// TODO Auto-generated constructor stub
	}

	public ClickstreamModel addRequest(HttpServletRequest request, HttpServletResponse response){
		if(request.getAttribute("CLICKSTREAM_RECORDED") != null){
			return (ClickstreamModel)WebUtils.getSessionAttribute(request, WebKeys.CLICKSTREAM_SESSION_ATTRIBUTE_KEY);
		}
		request.setAttribute("CLICKSTREAM_RECORDED", true);
		SiteModel site = pageResolver.getSite(request);
		HtmlPageModel page = pageResolver.getPage(request);
		
		HttpSession session = request.getSession();
		ClickstreamModel clickstream = (ClickstreamModel)request.getSession().getAttribute(WebKeys.CLICKSTREAM_SESSION_ATTRIBUTE_KEY);
		if (clickstream == null) {
			clickstream = new ClickstreamModel();
			session.setAttribute(WebKeys.CLICKSTREAM_SESSION_ATTRIBUTE_KEY, clickstream);
		}

		String associatedIdentifier = request.getParameter(WebKeys.CLICKSTREAM_CONTAINER_IDENTIFIER);
		if (StringUtils.isBlank(associatedIdentifier)) {
			associatedIdentifier = (String)request.getAttribute(WebKeys.CLICKSTREAM_IDENTIFIER_OVERRIDE);
		}
		//设置当前访问页面
		clickstream.setLastPageInode(page == null ? null : page.getInode());
		clickstream.setLastRequest(new Date());
		
		if (clickstream.getHostName() == null) {
			clickstream.setHostName(request.getRemoteHost());
		}
		if (clickstream.getRemoteAddress() == null) {
			clickstream.setRemoteAddress(request.getRemoteAddr());
		}

		// if this is the first request in the click stream
		if (null == clickstream.getClickstreamRequests() || clickstream.getClickstreamRequests().size() == 0) {
			// setup initial referrer
			if (request.getHeader("Referer") != null) {
				clickstream.setReferer(request.getHeader("Referer"));
			} else {
				clickstream.setReferer("");
			}

			if (request.getHeader("User-Agent") != null) {
				clickstream.setUserAgent(request.getHeader("User-Agent"));
			} else {
				clickstream.setUserAgent("");
			}
			BrowserSniffer bs = new BrowserSniffer(request.getHeader("User-Agent"));
			session.setAttribute("browserSniffer", bs);
			clickstream.setBrowserName(bs.getBrowserName());
			clickstream.setOperatingSystem(bs.getOS());
			clickstream.setBrowserVersion(bs.getBrowserVersion());
			clickstream.setMobileDevice(bs.isMobile());
			clickstream.setBot(BotChecker.isBot(request));
			clickstream.setFirstPageInode(page == null ? null : page.getInode());
			clickstream.setHostInode(site == null ? null : site.getInode());
		}

		// Set the cookie id to the long lived cookie
		if (StringUtils.isBlank(clickstream.getCookieId())) {
			Cookie cookie = WebUtils.getCookie(request, WebKeys.LONG_LIVED_DOTCMS_ID_COOKIE);
			if (null != cookie && StringUtils.isNotBlank(cookie.getValue())) {
				clickstream.setCookieId(cookie.getValue());
			}
		}

		// set the user if we have it
		if (UserContext.getAccountContext().getUserInode() != null && clickstream.getUserInode() == null) {
			setClickStreamUser(UserContext.getAccountContext().getUserInode(), request);
		}
		
		ClickstreamRequestModel cr = getClickstreamRequest(request, clickstream.getLastRequest());
		clickstream.setNumberOfRequests(clickstream.getNumberOfRequests() == null ? 0 : clickstream.getNumberOfRequests() + 1);
		cr.setRequestOrder(clickstream.getNumberOfRequests());


		cr.setHostInode(site.getInode());
		cr.setAssociatedIdentifier(associatedIdentifier);
		
		
		// prevent dupe entries into the clickstream table - just retun if the user is on the same page
		if(clickstream.getClickstreamRequests() != null &&clickstream.getClickstreamRequests().size()>0){
//			ClickstreamRequestModel last = clickstream.getClickstreamRequests().get(clickstream.getClickstreamRequests().size()-1);
//			if(last != null && StringUtils.equalsIgnoreCase(cr.getAssociatedIdentifier(), last.getAssociatedIdentifier())){
//				return clickstream;
//			}
		}
		
		clickstream.addClickstreamRequest(cr);        
		return clickstream;
	}
	
	/**
	 * This method sets the user for the current clickstream on login.
	 * 
	 * @param userId
	 *            the
	 * @param request
	 */

	public void setClickStreamUser(Long userId, HttpServletRequest request) {
		if (null == userId)
			return;

		HttpSession session = ((HttpServletRequest) request).getSession();
		ClickstreamModel clickstream = null;
		if (session.getAttribute("clickstream") == null) {
			clickstream = new ClickstreamModel();
		} else {
			clickstream = (ClickstreamModel) session.getAttribute("clickstream");
		}

		// overwrite if user is not already set
		if (null == clickstream.getUserInode()) {
			clickstream.setUserInode(userId);
		}
		session.setAttribute("clickstream", clickstream);
	}
	
	public ClickstreamRequestModel getClickstreamRequest(
			HttpServletRequest request, Date lastRequest) {
        HttpSession session = request.getSession();
        long languageId = 1l;
        if (session.getAttribute(WebKeys.HTMLPAGE_LANGUAGE) != null) {
            languageId = Long.parseLong(session.getAttribute(WebKeys.HTMLPAGE_LANGUAGE).toString());
        }

        String uri = request.getRequestURI();
        if(request.getAttribute(WebKeys.CLICKSTREAM_URI_OVERRIDE) != null){
            uri = (String) request.getAttribute(WebKeys.CLICKSTREAM_URI_OVERRIDE);
        }
        
        SiteModel host = pageResolver.getSite(request);
		
        ClickstreamRequestModel cr = new ClickstreamRequestModel();
        cr.setProtocol(request.getProtocol());
        cr.setServerName(request.getServerName());
        cr.setServerPort(request.getServerPort());
        cr.setQueryString(request.getQueryString());
        cr.setRemoteUser(request.getRemoteUser());
        cr.setRequestUri(uri);
        cr.setLanguageInode(languageId);
        cr.setTimeStampper(lastRequest);
        cr.setHostInode(host.getInode());
        return cr;
	}

	/**
	 * This method forces a clickstream save
	 * @param clickstream
	 */
	public void flushClickStream(ClickstreamModel clickstream) {
		if(wikiPreferences.getEnableClickTracking()){
			try {
				if (clickstream != null && clickstream.getClickstreamRequests() != null) {
					clickStreamService.save(clickstream);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}			
		}
		
	}

}
